package istar.behaviour;

import istar.IBasicElement;
import istar.IElement;
import istar.IElementLink;
import istar.ITask;
import istar.agent.IstarJadeAgent;
import istar.impl.Task;
import jade.core.behaviours.Behaviour;
import jade.core.behaviours.ParallelBehaviour;
import jade.core.behaviours.SequentialBehaviour;

import java.util.Iterator;

import log.Log;

public class SequentialTaskBehaviour extends SequentialBehaviour implements IistarBehaviour{

	Behaviour subBehaviour = null;

	private ITask endTask;
	private boolean log = true;
	private int step = 0;

	private boolean error = false;
	
	public SequentialTaskBehaviour(Task _end){
		super();
		this.endTask = _end;
		this.setBehaviourName("SequentialTaskBehaviour:"+_end.getName());
		//performBehaviour();
	}
	
	public SequentialTaskBehaviour(IstarJadeAgent _agent, Task _end){
		super(_agent);
		this.endTask = _end;
		this.setBehaviourName(_end.getName());
		//performBehaviour();
	}

	@Override
	public void onStart() {
		try {
			super.onStart();
			performBehaviour();
		} catch (Exception e) {
			error = true;
			this.endTask.getMain().getContent().clear();
			this.endTask.getMain().getContent().add(e.getMessage());
			//System.out.println(" >>>>> "+e.getMessage());;
		}
	}
	
	@Override
	public int onEnd() {
		if (error){
			((IstarJadeAgent)myAgent).log("Ending " + this.getBehaviourName() + " with error");
			//System.out.println("Ending " + this.getBehaviourName() + " with error");
			return ERROR_STATE_CODE;
		}
		else
			return myOnEnd();
	}
	

	private void performBehaviour() /*throws Exception*/{
		
		if (!this.getChildren().isEmpty()){
			Behaviour[] subs = new Behaviour[this.getChildren().size()];
			int i = 0;
			Iterator<Behaviour> itSubs = this.getChildren().iterator();
			while (itSubs.hasNext()){
				subs[i] = itSubs.next();
				i++;
			}
			for (int j=0;j<subs.length;j++){
				this.getChildren().remove(subs[j]);
			}
		}
		
		String subNames = "";
		Iterator<IElement> itTaskDecomp= endTask.getMyDecompositionLink().getTargetElements().iterator();
		while (itTaskDecomp.hasNext()){
			IElement subElemnt = itTaskDecomp.next();
			subNames += subElemnt.getName() + ";";
			subElemnt.getContent().addAll(endTask.getContent());
			
			// if subElemnt is internal
			if (subElemnt.getOwner()==endTask.getOwner()){
				//subElemnt.getContent().addAll(endTask.getContent());
				
				//((AbstractElement)subElemnt).setExecutionNumber(((AbstractElement)endTask).getExecutionNumber());
				
				if (subElemnt.isBasic()){
					subBehaviour = ((IBasicElement)subElemnt).getBehaviour();
					//System.out.println(this.myAgent.getLocalName()+ " Adding sub-behaviour " + subBehaviour.getBehaviourName());
				}
				else {
					if (subElemnt.getClass()==Task.class){
						((Task)subElemnt).setParams(endTask.getParams());
						if (((Task)subElemnt).getMyDecompositionLink().getType()==IElementLink.SEQUENTIAL){
							//this.addSubBehaviour(new SequentialTaskBehaviour((IstarJadeAgent)this.myAgent, (Task)subElemnt));
							subBehaviour = new SequentialTaskBehaviour((IstarJadeAgent)this.myAgent, (Task)subElemnt);
						}
						else if (((Task)subElemnt).getMyDecompositionLink().getType()==IElementLink.PARALLEL){
							//this.addSubBehaviour(new IstarParallelBehaviour((IstarJadeAgent)this.myAgent, (Task)subElemnt, ParallelBehaviour.WHEN_ALL));
							subBehaviour = new IstarParallelBehaviour((IstarJadeAgent)this.myAgent, (Task)subElemnt, ParallelBehaviour.WHEN_ALL);
						}
					}
					else {
						if (subElemnt.getMeansEndLink().getType()==IElementLink.PARALLEL){
							//this.addSubBehaviour(new IstarParallelBehaviour((IstarJadeAgent)this.myAgent, subElemnt, ParallelBehaviour.WHEN_ANY));
							subBehaviour = new IstarParallelBehaviour((IstarJadeAgent)this.myAgent, subElemnt, ParallelBehaviour.WHEN_ANY);
						}
						else if (subElemnt.getMeansEndLink().getType()==IElementLink.UNIQUE){
							//this.addSubBehaviour(new MeansEndUniqueBehaviour((IstarJadeAgent)this.myAgent, subElemnt));
							subBehaviour = new MeansEndUniqueBehaviour((IstarJadeAgent)this.myAgent, subElemnt);
						}
					}
				}
			}
			// subElemnt is external
			else {
				// send a request message
				//this.addSubBehaviour(new RequestExternalElement((IstarJadeAgent)this.myAgent, subElemnt));
				subBehaviour = new RequestExternalElement((IstarJadeAgent)this.myAgent, subElemnt, endTask);
			}
			log(this.getBehaviourName() + " has: " + subNames);
			log("behaviour name="+ getBehaviourName() + " adding subBehaviour " + subBehaviour.getBehaviourName()); 
			this.addSubBehaviour(subBehaviour);
		}
	}

	public int myOnEnd() {
		/*
		if (endTask.achieved()){
			//System.out.println("["+ this.myAgent.getLocalName()+ "] "+ this.getBehaviourName()+ " returning 1" );
			return 1;
		}
		else {
			//System.out.println("["+ this.myAgent.getLocalName()+ "] "+ this.getBehaviourName()+ " returning 0" );
			return 1;
		}
		*/
		return subBehaviour.onEnd();

	}
	
	public void log(String _phrase){
		if (this.log){
			((IstarJadeAgent)myAgent).log( _phrase);
		}
	}

	@Override
	public String getExecutionNumber() {
		return this.endTask.getExecutionNumber();
	}

	
	
}
